﻿using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Packaging;

namespace Songhay.OpenXml.Transformations
{
    using Songhay.OpenXml.Models;

    /// <summary>
    /// Transforms the Open XML WordML <c>r</c> element.
    /// </summary>
    [Export(typeof(IWordProcessingDocumentTransformation))]
    public class RunTransformation : IWordProcessingDocumentTransformation
    {
        #region IWordProcessingDocumentTransformation Members

        /// <summary>
        /// Gets or sets the execution ordinal.
        /// </summary>
        /// <value>The execution ordinal.</value>
        public byte ExecutionOrdinal { get; set; }

        /// <summary>
        /// Determines whether this instance can transform the specified word doc.
        /// </summary>
        /// <param name="wordDoc">The Word document.</param>
        /// <param name="settings">The settings.</param>
        /// <param name="node">The node.</param>
        /// <returns>
        /// 	<c>true</c> if this instance can transform the specified word doc; otherwise, <c>false</c>.
        /// </returns>
        public bool CanTransform(WordprocessingDocument wordDoc,
            SonghayHtmlConverterSettings settings, XNode node)
        {
            return this.HasElementName(node, SonghayW.r);
        }

        /// <summary>
        /// Transforms the specified Word document.
        /// </summary>
        /// <param name="wordDoc">The Word document.</param>
        /// <param name="settings">The settings.</param>
        /// <param name="node">The node.</param>
        /// <param name="imageHandler">The image handler.</param>
        public object Transform(WordprocessingDocument wordDoc,
            SonghayHtmlConverterSettings settings, XNode node,
            Func<ImageInfo, XElement> imageHandler)
        {
            var element = node as XElement;

            XElement rPrElement = null;

            #region selected run “property” elements:

            //Bold (w:b) to strong (h:strong):
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.b).Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.strong, rPrElement);
            }

            //Italics (w:i) to Emphasis (h:em):
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.i).Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.em, rPrElement);
            }

            //Smallcaps (w:smallCaps ) to Smallcaps span:
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.smallCaps).Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.span,
                    new XAttribute(SonghayXhtml.style_attr, "font-variant:small-caps;"),
                    rPrElement);
            }

            //Strikethrough (w:strike) to Strikethrough span:
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.strike).Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.span,
                    new XAttribute(SonghayXhtml.style_attr, "text-decoration:line-through;"),
                    rPrElement);
            }

            //Underline (w:u) to Underline span:
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.u).Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.span,
                    new XAttribute(SonghayXhtml.style_attr, "text-decoration:underline;"),
                    rPrElement);
            }

            //Vertical Alignment (w:vertAlign) to Subscript element (h:sub):
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.vertAlign)
                .Attributes(SonghayW.val).Where(a => a.Value == "subscript").Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.sub, rPrElement);
            }

            //Vertical Alignment (w:vertAlign) to Superscript element (h:sup):
            if(element.Elements(SonghayW.rPr).Elements(SonghayW.vertAlign)
                .Attributes(SonghayW.val).Where(a => a.Value == "superscript").Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.sup, rPrElement);
            }

            #endregion

            #region selected run styles:

            if(element.Elements(SonghayW.rPr).Elements(SonghayW.rStyle)
                .Attributes(SonghayW.val).Where(a => a.Value == "HTMLCode").Count() > 0)
            {
                rPrElement = new XElement(SonghayXhtml.code, rPrElement);
            }

            #endregion

            if(rPrElement != null)
            {
                rPrElement.DescendantsAndSelf().Last()
                    .Add(element.Elements()
                    .Select(e => OpenXmlUtility.TransformPackageNode(wordDoc,
                        settings, e, imageHandler)));
                return rPrElement;
            }

            // Transform contents of runs.
            return element.Elements()
                .Select(e => OpenXmlUtility.TransformPackageNode(wordDoc,
                    settings, e, imageHandler));
        }

        #endregion
    }
}
